/*
 *  tf_listmodel.cpp
 *  Perceel
 *
 *  Created by Nicola Gigante on 17/03/08.
 *  Copyright 2008 Nicola Gigante. All rights reserved.
 *
 */

#include "tf_list.h"

#include <QXmlStreamWriter>

QVariant TFList::data(const QModelIndex &index, int/* role */) const
{
	QVariant v = QVariant::fromValue(functions[index.row()]);
	
	return v;
}

void TFList::add(TF tf)
{
	beginInsertRows(QModelIndex(), functions.count() + 1, functions.count() + 1);
	functions.append(tf);
	endInsertRows();
	setModified(true);
}

void TFList::remove(int f)
{
	beginRemoveRows(QModelIndex(), f, f);
	functions.removeAt(f);
	endRemoveRows();
	setModified(true);
}

bool TFList::open(QString name)
{
	QFile f(name);
	if(!f.open(QIODevice::ReadOnly | QIODevice::Text))
		return false;
	
	setFilename(name);
	QList<TF> l;
	try
	{
		l = this->read(&f);
	}catch(...)
	{
		return false;
	}
	
	beginInsertRows(QModelIndex(), 0, l.count());
	functions = l;
	endInsertRows();
	setModified(false);
	
	return true;
}

bool TFList::save(QString filename)
{
	if(m_modified || this->filename() != filename)
	{
		setFilename(filename);
		QFile f(filename);
		if(!f.open(QIODevice::WriteOnly | QIODevice::Text))
			return false;
	
		this->write(&f);	
	
		f.close();
		setModified(false);
	}
	
	return true;
}

QList<TF> TFList::read(QIODevice *d) throw(IOError*)
{
	QDomDocument doc = QDomDocument("perceel");
	if(!doc.setContent(d))
		throw new IOError(IOError::Parse, tr("Parse error"));
	
	QList<TF> l;
	
	QDomElement docElem = doc.documentElement();
	
	if(docElem.tagName() != "perceel")
		throw new IOError(IOError::Parse, tr("Bad root tag."));
	
	QDomNodeList nodes = docElem.elementsByTagName("function");
	for(int i = 0; i < nodes.count(); i++)
	{
		TF tf;
		
		QDomNodeList roots = nodes.at(i).toElement().elementsByTagName("roots").at(0).toElement().elementsByTagName("root");
		
		for(int j = 0; j < roots.count(); j++)
		{
			Real real = roots.at(j).toElement().attribute("real", "0").toDouble();
			Real imag = roots.at(j).toElement().attribute("imag", "0").toDouble();
			
			Complex c(real, imag);
			tf.addRoot(c);
		}
		
		QDomNodeList poles = nodes.at(i).toElement().elementsByTagName("poles").at(0).toElement().elementsByTagName("pole");
		
		for(int j = 0; j < poles.count(); j++)
		{
			Real real = poles.at(j).toElement().attribute("real", "0").toDouble();
			Real imag = poles.at(j).toElement().attribute("imag", "0").toDouble();
			
			Complex c(real, imag);
			tf.addPole(c);
		}
		
		l.append(tf);
	}
	
	return l;
}


bool TFList::write(QIODevice *d)
{
	QXmlStreamWriter w(d);
	
	w.setAutoFormatting(true);
	
	w.writeStartDocument();
	w.writeStartElement("perceel");
	w.writeAttribute("version", "0.1");
	
	foreach(TF tf, functions)
	{
		w.writeStartElement("function");
		w.writeStartElement("roots");
		
		QList<Complex> roots = tf.roots();
		foreach(Complex r, roots)
		{
			w.writeEmptyElement("root");
			w.writeAttribute("real", QString::number(real(r)));
			w.writeAttribute("imag", QString::number(imag(r)));
		}
		w.writeEndElement(); // </roots>
		
		w.writeStartElement("poles");
		
		QList<Complex> poles = tf.poles();
		foreach(Complex p, poles)
		{
			w.writeEmptyElement("pole");
			w.writeAttribute("real", QString::number(real(p)));
			w.writeAttribute("imag", QString::number(imag(p)));
		}
		w.writeEndElement(); // </roots>
		
		w.writeEndElement(); // </function>
	}
	
	w.writeEndElement(); // </perceel>
	w.writeEndDocument();
	
	return true;
}
